home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-02 / pas_all.zip / TI226.ASC < prev    next >
Text File  |  1992-08-12  |  26KB  |  991 lines

  1.  
  2.  
  3.  
  4.  
  5.  
  6.  
  7.  
  8.  
  9.   PRODUCT : TURBO PASCAL                               NUMBER : 226
  10.   VERSION : 3.0xx
  11.        OS : PC-DOS
  12.      DATE : August 1, 1986                              PAGE : 1/15
  13.     TITLE : ASYNCHRONOUS COMMUNICATIONS
  14.  
  15.  
  16.  
  17.  
  18.   This version of Michael Quinlan's ASYNC.INC is compatible with
  19.   IBM PC and Compatibles. It gives interrupt-driven buffered
  20.   communication capabilities to Turbo programs written for the IBM
  21.   PC. It is heavily dependent on that hardware.
  22.  
  23.   **NOTE: Pages 12 through 15 contain an additional routine that
  24.   allows your program to change the communications parameters.
  25.  
  26.   The following example routines are public domain programs that
  27.   have been uploaded to our Forum on CompuServe. As a courtesy to
  28.   our users that do not have immediate access to CompuServe,
  29.   Technical Support distributes these routines free of charge.
  30.  
  31.   However, because these routines are public domain programs, not
  32.   developed by Borland International, we are unable to provide any
  33.   technical support or assistance using these routines. If you need
  34.   assistance using these routines, or are experiencing difficu
  35.  
  36.   {--------------------------------------------------------------}
  37.   {                        ASYNC.INC                             }
  38.   {                                                              }
  39.   {  Async Communication Routines                                }
  40.   {  by Michael Quinlan                                          }
  41.   {  with a bug fixed by Scott Herr                              }
  42.   {  made PCjr-compatible by W. M. Miller                        }
  43.   {  Highly dependent on the IBM PC and PC DOS 2.0               }
  44.   {                                                              }
  45.   {  based on the DUMBTERM program by CJ Dunford                 }
  46.   {  in the January 1984                                         }
  47.   {  issue of PC Tech Journal.                                   }
  48.   {                                                              }
  49.   {  Entry points:                                               }
  50.   {    Async_Init                                                }
  51.   {      Performs initialization.                                }
  52.   {                                                              }
  53.   {    Async_Open(Port, Baud : Integer;                          }
  54.   {               Parity : Char;                                 }
  55.   {               WordSize, StpBits : Integer) : Boolean         }
  56.   {   Sets up interrupt vector, initialize the COM port for      }
  57.   {   processing, sets pointers to the buffer.  Returns FALSE    }
  58.   {   if COM                                                     }
  59.   {      port not installed.                                     }
  60.   {                                                              }
  61.  
  62.  
  63.  
  64.  
  65.  
  66.  
  67.  
  68.  
  69.  
  70.  
  71.  
  72.  
  73.  
  74.  
  75.   PRODUCT : TURBO PASCAL                               NUMBER : 226
  76.   VERSION : 3.0xx
  77.        OS : PC-DOS
  78.      DATE : August 1, 1986                              PAGE : 2/15
  79.     TITLE : ASYNCHRONOUS COMMUNICATIONS
  80.  
  81.  
  82.  
  83.  
  84.   {    Async_Buffer_Check(var C : Char) : Boolean                }
  85.   {      If a character is available, returns TRUE and moves the }
  86.   {        character from the buffer to the parameter            }
  87.   {      Otherwise, returns FALSE                                }
  88.   {                                                              }
  89.   {    Async_Send(C : Char)                                      }
  90.   {      Transmits the character.                                }
  91.  
  92.   {    Async_Send_String(S : LStr)                               }
  93.   {      Calls Async_Send to send each character of S.           }
  94.   {    Async_Close                                               }
  95.   {    Turn off the COM port interrupts.                         }
  96.   {    **MUST** BE CALLED BEFORE EXITING                         }
  97.   {    YOUR PROGRAM; otherwise you                               }
  98.   {    will see some really strange errors and have to re-boot.  }
  99.   {--------------------------------------------------------------}
  100.   { global declarations }
  101.  
  102.   type
  103.     LStr = String[255];  { generic string type for parameters }
  104.  
  105.   const
  106.     UART_THR = $00;
  107.         { offset from base of UART Registers for IBM PC }
  108.     UART_RBR = $00;
  109.     UART_IER = $01;
  110.     UART_IIR = $02;
  111.     UART_LCR = $03;
  112.     UART_MCR = $04;
  113.     UART_LSR = $05;
  114.     UART_MSR = $06;
  115.  
  116.     I8088_IMR = $21;
  117.          { port address of the Interrupt Mask Register }
  118.  
  119.   const
  120.     Async_DSeg_Save : Integer = 0;
  121.                        { Save DS reg in Code Segment
  122.                        for interrupt routine }
  123.  
  124.   const
  125.     Async_Buffer_Max = 4095;
  126.  
  127.  
  128.  
  129.  
  130.  
  131.  
  132.  
  133.  
  134.  
  135.  
  136.  
  137.  
  138.  
  139.  
  140.  
  141.   PRODUCT : TURBO PASCAL                               NUMBER : 226
  142.   VERSION : 3.0xx
  143.        OS : PC-DOS
  144.      DATE : August 1, 1986                              PAGE : 3/15
  145.     TITLE : ASYNCHRONOUS COMMUNICATIONS
  146.  
  147.  
  148.  
  149.  
  150.   var
  151.     Async_Buffer    : Array[0..Async_Buffer_Max] of char;
  152.     Async_Open_Flag : Boolean;
  153.     Async_Port      : Integer; { current Open port number (1 or 2) }
  154.     Async_Base      : Integer; { base for current open port }
  155.     Async_Irq       : Integer; { irq for current open port }
  156.  
  157.     Async_Buffer_Overflow : Boolean;
  158.              { True if buffer overflow has happened }
  159.     Async_Buffer_Used     : Integer;
  160.     Async_MaxBufferUsed   : Integer;
  161.  
  162.       { Async_Buffer is empty if Head = Tail }
  163.     Async_Buffer_Head  : Integer;
  164.              { Locn in Async_Buffer to put next char }
  165.     Async_Buffer_Tail  : Integer;
  166.              { Locn in Async_Buffer to get next char }
  167.     Async_Buffer_NewTail : Integer;
  168.  
  169.     Async_BIOS_Port_Table : Array[1..2] of Integer absolute $40:0;
  170.       { This table is initialized by BIOS equipment determination
  171.       code at boot time to contain the base addresses for the
  172.       installed async adapters.  A value of 0 means "not in-
  173.       stalled." }
  174.  
  175.   const
  176.     Async_Num_Bauds = 8;
  177.     Async_Baud_Table : array [1..Async_Num_Bauds] of record
  178.                                            Baud, Bits : integer
  179.                                         end
  180.                      = ((Baud:110;  Bits:$00),
  181.                         (Baud:150;  Bits:$20),
  182.                         (Baud:300;  Bits:$40),
  183.                         (Baud:600;  Bits:$60),
  184.                         (Baud:1200; Bits:$80),
  185.                         (Baud:2400; Bits:$A0),
  186.                         (Baud:4800; Bits:$C0),
  187.                         (Baud:9600; Bits:$E0));
  188.  
  189.   procedure BIOS_RS232_Init(ComPort, ComParm : Integer);
  190.   { Issue Interrupt $14 to initialize the UART }
  191.   { See the IBM PC Technical Reference Manual
  192.     for the format of ComParm }
  193.  
  194.  
  195.  
  196.  
  197.  
  198.  
  199.  
  200.  
  201.  
  202.  
  203.  
  204.  
  205.  
  206.  
  207.   PRODUCT : TURBO PASCAL                               NUMBER : 226
  208.   VERSION : 3.0xx
  209.        OS : PC-DOS
  210.      DATE : August 1, 1986                              PAGE : 4/15
  211.     TITLE : ASYNCHRONOUS COMMUNICATIONS
  212.  
  213.  
  214.  
  215.  
  216.   var
  217.     Regs : record
  218.              ax, bx, cx, dx, bp, si, di, ds, es, flag : Integer
  219.            end;
  220.   begin
  221.     with Regs do
  222.       begin
  223.         ax := ComParm and $00FF;  { AH=0; AL=ComParm }
  224.         dx := ComPort;
  225.         Intr($14, Regs)
  226.       end
  227.   end; { BIOS_RS232_Init }
  228.  
  229.   procedure DOS_Set_Intrpt(v, s, o : integer);
  230.   { call DOS to set an interrupt vector }
  231.   var
  232.     Regs : Record
  233.              ax, bx, cx, dx, bp, si, di, ds, es, flag : integer
  234.            end;
  235.   begin
  236.     with Regs do
  237.       begin
  238.         ax := $2500 + (v and $00FF);
  239.         ds := s;
  240.         dx := o;
  241.         MsDos(Regs)
  242.       end
  243.   end; { DOS_Set_Intrpt }
  244.  
  245.   {----------------------------------------------------------}
  246.   {                                                          }
  247.   {  ASYNCISR.INC - Interrupt Service Routine                }
  248.   {                                                          }
  249.   {----------------------------------------------------------}
  250.  
  251.   procedure Async_Isr;
  252.   { Interrupt Service Routine }
  253.   { Invoked when the UART has received a byte of data from the
  254.     communication line }
  255.  
  256.   { re-written 9/14/84 to be entirely in machine language;
  257.     original source left as comments }
  258.  
  259.  
  260.  
  261.  
  262.  
  263.  
  264.  
  265.  
  266.  
  267.  
  268.  
  269.  
  270.  
  271.  
  272.  
  273.   PRODUCT : TURBO PASCAL                               NUMBER : 226
  274.   VERSION : 3.0xx
  275.        OS : PC-DOS
  276.      DATE : August 1, 1986                              PAGE : 5/15
  277.     TITLE : ASYNCHRONOUS COMMUNICATIONS
  278.  
  279.  
  280.  
  281.  
  282.   begin
  283.  
  284.     {NOTE: on entry, Turbo Pascal has already PUSHed BP and SP }
  285.     Inline(
  286.         { save all registers used }
  287.       $50/                           { PUSH AX }
  288.       $53/                           { PUSH BX }
  289.       $52/                           { PUSH DX }
  290.       $1E/                           { PUSH DS }
  291.       $FB/                           { STI }
  292.      { set up the DS register to point to Turbo Pascal's data segment }
  293.       $2E/$FF/$36/Async_Dseg_Save/   { PUSH CS:Async_Dseg_Save }
  294.       $1F/                           { POP DS }
  295.      { get the incoming character }
  296.      { Async_Buffer[Async_Buffer_Head]
  297.                     := Chr(Port[UART_RBR + Async_Base]); }
  298.       $8B/$16/Async_Base/            { MOV DX,Async_Base }
  299.       $EC/                           { IN AL,DX }
  300.       $8B/$1E/Async_Buffer_Head/     { MOV BX,Async_Buffer_Head }
  301.       $88/$87/Async_Buffer/          { MOV Async_Buffer[BX],AL }
  302.         { Async_Buffer_NewHead := Async_Buffer_Head + 1; }
  303.       $43/                           { INC BX }
  304.         { if Async_Buffer_NewHead > Async_Buffer_Max then
  305.             Async_Buffer_NewHead := 0; }
  306.       $81/$FB/Async_Buffer_Max/      { CMP BX,Async_Buffer_Max }
  307.       $7E/$02/                       { JLE L001 }
  308.       $33/$DB/                       { XOR BX,BX }
  309.         { if Async_Buffer_NewHead = Async_Buffer_Tail then
  310.             Async_Buffer_Overflow := TRUE
  311.           else }
  312.   {L001:}
  313.      $3B/$1E/Async_Buffer_Tail/     { CMP BX,Async_Buffer_Tail }
  314.      $75/$08/                       { JNE L002 }
  315.      $C6/$06/Async_Buffer_Overflow/$01/ { MOV Async_Buffer_Overflow,1 }
  316.      $90/                           { NOP generated by assembler
  317.                                       for some reason }
  318.      $EB/$16/                       { JMP SHORT L003 }
  319.        { begin
  320.            Async_Buffer_Head := Async_Buffer_NewHead;
  321.            Async_Buffer_Used := Async_Buffer_Used + 1;
  322.            if Async_Buffer_Used > Async_MaxBufferUsed then
  323.              Async_MaxBufferUsed := Async_Buffer_Used
  324.          end; }
  325.  
  326.  
  327.  
  328.  
  329.  
  330.  
  331.  
  332.  
  333.  
  334.  
  335.  
  336.  
  337.  
  338.  
  339.   PRODUCT : TURBO PASCAL                               NUMBER : 226
  340.   VERSION : 3.0xx
  341.        OS : PC-DOS
  342.      DATE : August 1, 1986                              PAGE : 6/15
  343.     TITLE : ASYNCHRONOUS COMMUNICATIONS
  344.  
  345.  
  346.  
  347.  
  348.   {L002:}
  349.      $89/$1E/Async_Buffer_Head/     { MOV Async_Buffer_Head,BX }
  350.      $FF/$06/Async_Buffer_Used/     { INC Async_Buffer_Used }
  351.      $8B/$1E/Async_Buffer_Used/     { MOV BX,Async_Buffer_Used }
  352.      $3B/$1E/Async_MaxBufferUsed/   { CMP BX,Async_MaxBufferUsed }
  353.      $7E/$04/                       { JLE L003 }
  354.      $89/$1E/Async_MaxBufferUsed/   { MOV Async_MaxBufferUsed,BX }
  355.   {L003:}
  356.        { disable interrupts }
  357.      $FA/                           { CLI }
  358.        { Port[$20] := $20; }  { use non-specific EOI }
  359.      $B0/$20/                       { MOV AL,20h }
  360.      $E6/$20/                       { OUT 20h,AL }
  361.        { restore the registers then use IRET to return }
  362.        { the last two POPs are required because Turbo Pascal
  363.          PUSHes these regs before we get control.  The manual
  364.          doesn't so it, but that is what really happens }
  365.      $1F/                           { POP DS }
  366.      $5A/                           { POP DX }
  367.      $5B/                           { POP BX }
  368.      $58/                           { POP AX }
  369.      $5C/                           { POP SP }
  370.      $5D/                           { POP BP }
  371.      $CF)                           { IRET }
  372.   end; { Async_Isr }
  373.  
  374.   procedure Async_Init;
  375.   { initialize variables }
  376.   begin
  377.     Async_DSeg_Save := DSeg;
  378.     Async_Open_Flag := FALSE;
  379.     Async_Buffer_Overflow := FALSE;
  380.     Async_Buffer_Used := 0;
  381.     Async_MaxBufferUsed := 0;
  382.   end; { Async_Init }
  383.  
  384.   procedure Async_Close;
  385.   { reset the interrupt system when UART interrupts
  386.     no longer needed }
  387.   var
  388.     i, m : Integer;
  389.   begin
  390.     if Async_Open_Flag then
  391.  
  392.  
  393.  
  394.  
  395.  
  396.  
  397.  
  398.  
  399.  
  400.  
  401.  
  402.  
  403.  
  404.  
  405.   PRODUCT : TURBO PASCAL                               NUMBER : 226
  406.   VERSION : 3.0xx
  407.        OS : PC-DOS
  408.      DATE : August 1, 1986                              PAGE : 7/15
  409.     TITLE : ASYNCHRONOUS COMMUNICATIONS
  410.  
  411.  
  412.  
  413.  
  414.       begin
  415.  
  416.         { disable the IRQ on the 8259 }
  417.         Inline($FA);         { disable interrupts }
  418.         i := Port[I8088_IMR];
  419.                              { get the interrupt mask register }
  420.         m := 1 shl Async_Irq;
  421.                              { set mask to turn off interrupt }
  422.         Port[I8088_IMR] := i or m;
  423.  
  424.         { disable the 8250 data ready interrupt }
  425.         Port[UART_IER + Async_Base] := 0;
  426.  
  427.         { disable OUT2 on the 8250 }
  428.         Port[UART_MCR + Async_Base] := 0;
  429.         Inline($FB);          { enable interrupts }
  430.  
  431.         { re-initialize our data areas so
  432.           we know the port is closed }
  433.         Async_Open_Flag := FALSE
  434.  
  435.       end
  436.   end; { Async_Close }
  437.  
  438.   function Async_Open(ComPort       : Integer;
  439.                       BaudRate      : Integer;
  440.                       Parity        : Char;
  441.                       WordSize      : Integer;
  442.                       StopBits      : Integer) : Boolean;
  443.   { open a communications port }
  444.   var
  445.     ComParm : Integer;
  446.     i, m : Integer;
  447.   begin
  448.     if Async_Open_Flag then Async_Close;
  449.  
  450.     if (ComPort = 2) and (Async_BIOS_Port_Table[2] <> 0) then
  451.       Async_Port := 2
  452.     else
  453.       Async_Port := 1;  { default to COM1 }
  454.     Async_Base := Async_BIOS_Port_Table[Async_Port];
  455.     Async_Irq := Hi(Async_Base) + 1;
  456.  
  457.  
  458.  
  459.  
  460.  
  461.  
  462.  
  463.  
  464.  
  465.  
  466.  
  467.  
  468.  
  469.  
  470.  
  471.   PRODUCT : TURBO PASCAL                               NUMBER : 226
  472.   VERSION : 3.0xx
  473.        OS : PC-DOS
  474.      DATE : August 1, 1986                              PAGE : 8/15
  475.     TITLE : ASYNCHRONOUS COMMUNICATIONS
  476.  
  477.  
  478.  
  479.  
  480.     if (Port[UART_IIR + Async_Base] and $00F8) <> 0 then
  481.       Async_Open := FALSE
  482.     else
  483.       begin
  484.         Async_Buffer_Head := 0;
  485.         Async_Buffer_Tail := 0;
  486.         Async_Buffer_Overflow := FALSE;
  487.  
  488.     { Build the ComParm for RS232_Init }
  489.     { See Technical Reference Manual for description }
  490.  
  491.         ComParm := $0000;
  492.  
  493.     { Set up the bits for the baud rate }
  494.         i := 0;
  495.         repeat
  496.           i := i + 1
  497.         until (Async_Baud_Table[i].Baud = BaudRate)
  498.                 or (i = Async_Num_Bauds);
  499.         ComParm := ComParm or Async_Baud_Table[i].Bits;
  500.  
  501.         if Parity in ['E', 'e'] then ComParm := ComParm or $0018
  502.         else if Parity in ['O', 'o'] then
  503.              ComParm := ComParm or $0008
  504.         else ComParm := ComParm or $0000;  { default to No parity }
  505.  
  506.         if WordSize = 7 then ComParm := ComParm or $0002
  507.         else ComParm := ComParm or $0003;  { default to 8 data bits }
  508.  
  509.         if StopBits = 2 then ComParm := ComParm or $0004
  510.         else ComParm := ComParm or $0000;  { default to 1 stop bit }
  511.  
  512.         { use the BIOS COM port initialization routine
  513.           to save typing the code }
  514.  
  515.         BIOS_RS232_Init(Async_Port - 1, ComParm);
  516.  
  517.         DOS_Set_Intrpt(Async_Irq + 8, CSeg, Ofs(Async_Isr));
  518.  
  519.   { read the RBR and reset any possible pending error conditions
  520.     first turn off the Divisor Access Latch Bit to allow
  521.     access to RBR, etc. }
  522.  
  523.  
  524.  
  525.  
  526.  
  527.  
  528.  
  529.  
  530.  
  531.  
  532.  
  533.  
  534.  
  535.  
  536.  
  537.   PRODUCT : TURBO PASCAL                               NUMBER : 226
  538.   VERSION : 3.0xx
  539.        OS : PC-DOS
  540.      DATE : August 1, 1986                              PAGE : 9/15
  541.     TITLE : ASYNCHRONOUS COMMUNICATIONS
  542.  
  543.  
  544.  
  545.  
  546.         Inline($FA);  { disable interrupts }
  547.  
  548.         Port[UART_LCR + Async_Base] :=
  549.                 Port[UART_LCR + Async_Base] and $7F;
  550.         { read the Line Status Register to reset any
  551.           errors it indicates }
  552.         i := Port[UART_LSR + Async_Base];
  553.         { read the Receiver Buffer Register in case
  554.           it contains a character }
  555.         i := Port[UART_RBR + Async_Base];
  556.  
  557.         { enable the irq on the 8259 controller }
  558.         i := Port[I8088_IMR];  { get the interrupt mask register }
  559.         m := (1 shl Async_Irq) xor $00FF;
  560.         Port[I8088_IMR] := i and m;
  561.  
  562.         { enable the data ready interrupt on the 8250 }
  563.         Port[UART_IER + Async_Base] := $01;
  564.         { enable data ready interrupt }
  565.  
  566.         { enable OUT2 on 8250 }
  567.         i := Port[UART_MCR + Async_Base];
  568.         Port[UART_MCR + Async_Base] := i or $08;
  569.         Inline($FB); { enable interrupts }
  570.         Async_Open_Flag := TRUE;  { bug fix by Scott Herr }
  571.         Async_Open := TRUE
  572.       end
  573.   end; { Async_Open }
  574.  
  575.   function Async_Buffer_Check(var C : Char) : Boolean;
  576.   { see if a character has been received; return it if yes }
  577.   begin
  578.     if Async_Buffer_Head = Async_Buffer_Tail then
  579.       Async_Buffer_Check := FALSE
  580.     else
  581.       begin
  582.         C := Async_Buffer[Async_Buffer_Tail];
  583.         Async_Buffer_Tail := Async_Buffer_Tail + 1;
  584.         if Async_Buffer_Tail > Async_Buffer_Max then
  585.           Async_Buffer_Tail := 0;
  586.         Async_Buffer_Used := Async_Buffer_Used - 1;
  587.         Async_Buffer_Check := TRUE
  588.       end
  589.  
  590.  
  591.  
  592.  
  593.  
  594.  
  595.  
  596.  
  597.  
  598.  
  599.  
  600.  
  601.  
  602.  
  603.   PRODUCT : TURBO PASCAL                               NUMBER : 226
  604.   VERSION : 3.0xx
  605.        OS : PC-DOS
  606.      DATE : August 1, 1986                             PAGE : 10/15
  607.     TITLE : ASYNCHRONOUS COMMUNICATIONS
  608.  
  609.  
  610.  
  611.  
  612.   end; { Async_Buffer_Check }
  613.  
  614.   procedure Async_Send(C : Char);
  615.   { transmit a character }
  616.   var
  617.     i, m, counter : Integer;
  618.   begin
  619.     Port[UART_MCR + Async_Base] := $0B; { turn on OUT2, DTR, and RTS }
  620.  
  621.     { wait for CTS }
  622.     counter := MaxInt;
  623.     while (counter <> 0) and
  624.           ((Port[UART_MSR + Async_Base] and $10) = 0) do
  625.       counter := counter - 1;
  626.  
  627.     { wait for Transmit Hold Register Empty (THRE) }
  628.     if counter <> 0 then counter := MaxInt;
  629.     while (counter <> 0) and
  630.           ((Port[UART_LSR + Async_Base] and $20) = 0) do
  631.       counter := counter - 1;
  632.     if counter <> 0 then
  633.       begin
  634.         { send the character }
  635.         Inline($FA); { disable interrupts }
  636.         Port[UART_THR + Async_Base] := Ord(C);
  637.         Inline($FB) { enable interrupts }
  638.       end
  639.     else
  640.       writeln('<<<TIMEOUT>>>');
  641.   end; { Async_Send }
  642.  
  643.   procedure Async_Send_String(S : LStr);
  644.   { transmit a string }
  645.   var
  646.     i : Integer;
  647.   begin
  648.     for i := 1 to length(S) do
  649.       Async_Send(S[i])
  650.   end; { Async_Send_String }
  651.  
  652.   ________________________________________________________________
  653.  
  654.                           CHANGE PARAMETERS
  655.  
  656.  
  657.  
  658.  
  659.  
  660.  
  661.  
  662.  
  663.  
  664.  
  665.  
  666.  
  667.  
  668.  
  669.   PRODUCT : TURBO PASCAL                               NUMBER : 226
  670.   VERSION : 3.0xx
  671.        OS : PC-DOS
  672.      DATE : August 1, 1986                             PAGE : 11/15
  673.     TITLE : ASYNCHRONOUS COMMUNICATIONS
  674.  
  675.  
  676.  
  677.  
  678.   ________________________________________________________________
  679.  
  680.  
  681.   { ASYCHG.INC - procedure to change communication parameters }
  682.   { "on the fly" must be Included following ASYNC.INC }
  683.  
  684.   procedure Async_Change(BaudRate      : Integer;
  685.                          Parity        : Char;
  686.                          WordSize      : Integer;
  687.                          StopBits      : Integer);
  688.   { change communication parameters "on the fly" }
  689.   { you cannot use the BIOS routines because they drop DTR }
  690.  
  691.   const num_bauds = 15;
  692.       divisor_table : array [1..num_bauds] of record
  693.                                               baud, divisor : integer
  694.                                             end
  695.          = ((baud:50;  divisor:2304),
  696.             (baud:75;  divisor:1536),
  697.             (baud:110; divisor:1047),
  698.             (baud:134; divisor:857),
  699.             (baud:150; divisor:768),
  700.             (baud:300; divisor:384),
  701.             (baud:600; divisor:192),
  702.             (baud:1200; divisor:96),
  703.             (baud:1800; divisor:64),
  704.             (baud:2000; divisor:58),
  705.             (baud:2400; divisor:48),
  706.             (baud:3600; divisor:32),
  707.             (baud:4800; divisor:24),
  708.             (baud:7200; divisor:16),
  709.             (baud:9600; divisor:12));
  710.  
  711.   var i : integer;
  712.       dv  : integer;
  713.       lcr : integer;
  714.  
  715.   begin
  716.  
  717.     { Build the Line Control Register and find
  718.       the divisor (for the baud rate) }
  719.  
  720.     { Set up the divisor for the baud rate }
  721.  
  722.  
  723.  
  724.  
  725.  
  726.  
  727.  
  728.  
  729.  
  730.  
  731.  
  732.  
  733.  
  734.  
  735.   PRODUCT : TURBO PASCAL                               NUMBER : 226
  736.   VERSION : 3.0xx
  737.        OS : PC-DOS
  738.      DATE : August 1, 1986                             PAGE : 12/15
  739.     TITLE : ASYNCHRONOUS COMMUNICATIONS
  740.  
  741.  
  742.  
  743.  
  744.     i := 0;
  745.     repeat
  746.       i := i + 1
  747.     until (Divisor_Table[i].Baud = BaudRate) or (i = Num_Bauds);
  748.     dv  := Divisor_Table[i].divisor;
  749.  
  750.     lcr := 0;
  751.     case Parity of
  752.       'E' : lcr := lcr or $18;  { even parity }
  753.       'O' : lcr := lcr or $08;  { odd parity }
  754.       'N' : lcr := lcr or $00;  { no parity }
  755.       'M' : lcr := lcr or $28;  { Mark parity }
  756.       'S' : lcr := lcr or $38;  { Space parity }
  757.     else
  758.       lcr := lcr or $00;  { default to no parity }
  759.     end;
  760.  
  761.     case WordSize of
  762.       5 : lcr := lcr or $00;
  763.       6 : lcr := lcr or $01;
  764.       7 : lcr := lcr or $02;
  765.       8 : lcr := lcr or $03;
  766.     else
  767.       lcr := lcr or $03;  { default to 8 data bits }
  768.     end;
  769.  
  770.     if StopBits = 2 then lcr := lcr or $04
  771.     else lcr := lcr or $00;  { default to 1 stop bit }
  772.  
  773.     lcr := lcr and $7F;   { make certain the DLAB is off }
  774.  
  775.     Inline($FA);  { disable interrupts }
  776.  
  777.     { turn on DLAB to access the divisor }
  778.     Port[UART_LCR + Async_Base] := Port[UART_LCR + Async_Base] or $80;
  779.  
  780.     { set the divisor }
  781.     Port[Async_Base] := Lo(dv);
  782.     Port[Async_Base + 1] := Hi(dv);
  783.  
  784.     { turn off the DLAB and set the new comm. parameters }
  785.     Port[UART_LCR + Async_Base] := lcr;
  786.  
  787.  
  788.  
  789.  
  790.  
  791.  
  792.  
  793.  
  794.  
  795.  
  796.  
  797.  
  798.  
  799.  
  800.  
  801.   PRODUCT : TURBO PASCAL                               NUMBER : 226
  802.   VERSION : 3.0xx
  803.        OS : PC-DOS
  804.      DATE : August 1, 1986                             PAGE : 13/15
  805.     TITLE : ASYNCHRONOUS COMMUNICATIONS
  806.  
  807.  
  808.  
  809.  
  810.     Inline($FB);  { enable interrupts }
  811.  
  812.   end; { Async_Change }
  813.  
  814.   The following are two example programs which use ASYNC.INC.
  815.  
  816.     program DumbTerminal;
  817.     {$C-}
  818.     {$I ASYNC.INC}
  819.     var
  820.       ch: Char;
  821.       stop: Boolean;
  822.     begin
  823.       stop := false;
  824.       Async_Init;
  825.       if not Async_Open(1, 1200, 'E', 7, 1) then
  826.         begin
  827.           writeln('Invalid port');
  828.           Halt
  829.         end;
  830.       LowVideo;
  831.        writeln('COM1 now open at 1200 baud, 7 data bits, even parity, ',
  832.               '1 stop bit.');
  833.       write('All keyboard input will be sent out COM1');
  834.       writeln('all input from COM1');
  835.       writeln('will be displayed on the screen.  To quit, type ^Z.');
  836.       writeln;
  837.       repeat
  838.         if Async_Buffer_Check(ch) then write(ch);
  839.         if KeyPressed then
  840.           begin
  841.             read(Kbd, ch);
  842.             if ch = ^Z then stop := true else Async_Send(ch)
  843.           end
  844.       until stop;
  845.       Async_Close
  846.     end.
  847.  
  848.   program tty;
  849.  
  850.   {$IASYNC.INC}
  851.  
  852.   var
  853.  
  854.  
  855.  
  856.  
  857.  
  858.  
  859.  
  860.  
  861.  
  862.  
  863.  
  864.  
  865.  
  866.  
  867.   PRODUCT : TURBO PASCAL                               NUMBER : 226
  868.   VERSION : 3.0xx
  869.        OS : PC-DOS
  870.      DATE : August 1, 1986                             PAGE : 14/15
  871.     TITLE : ASYNCHRONOUS COMMUNICATIONS
  872.  
  873.  
  874.  
  875.  
  876.     c : char;
  877.  
  878.   begin
  879.     Async_Init;  { initialize variables }
  880.     if not Async_Open(1, 1200, 'E', 7, 1) then  {open communications
  881.   port}
  882.       begin
  883.         writeln('**ERROR: Async_Open failed');
  884.         halt
  885.       end;
  886.  
  887.     writeln('TTY Emulation begins now...');
  888.     writeln('Press any function key to terminate...');
  889.  
  890.     repeat
  891.       if Async_Buffer_Check(c) then
  892.         case c of
  893.           #000 : ;  { strip incoming nulls }
  894.           #010 : ;  { strip incoming line feeds }
  895.           #012 : ClrScr;  { clear screen on a form feed }
  896.           #013 : Writeln  { handle carriage return as CR/LF }
  897.         else
  898.           write(c)  { else write incoming char to the screen }
  899.         end; { case }
  900.       if KeyPressed then
  901.         begin
  902.           Read(Kbd, c);
  903.           if c = #027 then  { handle IBM Extended Ascii codes }
  904.             begin
  905.               Read(Kbd, c);  { clear the rest of the extended code }
  906.               Async_Close;   { reset the interrupt system, etc. }
  907.               Writeln('End of TTY Emulation...');
  908.               Writeln('Max Buffer Used = ', Async_MaxBufferUsed);
  909.               halt          { terminate the program }
  910.             end
  911.           else
  912.             Async_Send(c)
  913.         end
  914.     until FALSE
  915.  
  916.   end.
  917.  
  918.  
  919.  
  920.  
  921.  
  922.  
  923.  
  924.  
  925.  
  926.  
  927.  
  928.  
  929.  
  930.  
  931.  
  932.  
  933.   PRODUCT : TURBO PASCAL                               NUMBER : 226
  934.   VERSION : 3.0xx
  935.        OS : PC-DOS
  936.      DATE : August 1, 1986                             PAGE : 15/15
  937.     TITLE : ASYNCHRONOUS COMMUNICATIONS
  938.  
  939.  
  940.  
  941.  
  942.   DISCLAIMER: You have the right to use this technical information
  943.   subject to the terms of the No-Nonsense License Statement that
  944.   you received with the Borland product to which this information
  945.   pertains.
  946.  
  947.  
  948.  
  949.  
  950.  
  951.  
  952.  
  953.  
  954.  
  955.  
  956.  
  957.  
  958.  
  959.  
  960.  
  961.  
  962.  
  963.  
  964.  
  965.  
  966.  
  967.  
  968.  
  969.  
  970.  
  971.  
  972.  
  973.  
  974.  
  975.  
  976.  
  977.  
  978.  
  979.  
  980.  
  981.  
  982.  
  983.  
  984.  
  985.  
  986.  
  987.  
  988.  
  989.  
  990.  
  991.